#coding: utf-8 
from room import *
from doors import *
import networkx as nx

class GlobalCleanTask:
	
	def __init__(self,robots,building):
		self.robots=robots
		self.building=building
		
		self.g=nx.Graph()
		self.add_nodes_and_edges(building.path.graph)
	
	def add_nodes_and_edges(self,bgraph):
		self.g.add_nodes_from(bgraph.keys())
		for node,edges in bgraph.items():
			for edge in edges.keys():
				self.g.add_edge(node,edge)
		#~ print self.g.edges()
		#~ print self.g.nodes()
	
		
	def buildCleanGraph(self):
		u"""Constroi um grafo em que cada nó é um compartimento a limpar,
		cada caminho é uma porta. As portas não têm peso, os compartimentos
		têm o peso do tempo a limpar do mesmo, dado pelo seu genoma vencedor.
		"""
		
	def splitGraph(self,graph,bnode):
		
		graph = graph.subgraph(graph.nodes())
		
		if bnode not in graph.nodes():
			return [graph]
		
		union_nodes = graph.neighbors(bnode)
		graph.remove_node(bnode)
		
		aux_union_nodes = copy(union_nodes)
		for node in union_nodes:
			if isinstance(node,Door):
				aux_union_nodes.remove(node)
		union_nodes = aux_union_nodes
		
		all_nodes=graph.nodes()
		found_nodes={}
		explore_nodes=[]
		if(len(union_nodes)==1):
			return [graph]
		
		for i in range(len(union_nodes)):
			found_nodes[union_nodes[i]]=i
			explore_nodes.append(union_nodes[i])
			
		while len(explore_nodes)>0:
			next_explore_nodes=[]
			print explore_nodes
			
			for enode in explore_nodes:
				for fnode in graph.neighbors(enode):
					if isinstance(fnode,Door) and isinstance(enode,Door):
						pass
					elif fnode not in found_nodes.keys():
						found_nodes[fnode] = found_nodes[enode]
						next_explore_nodes.append(fnode)
					elif found_nodes[fnode] != found_nodes[enode]:
						#fnode está ligado a enode
						for node in found_nodes.keys():
							if found_nodes[node] is found_nodes[fnode]:
								found_nodes[node] = found_nodes[enode]
			explore_nodes=next_explore_nodes
		
		result_nodes={}
		for node,number in found_nodes.items():
			try:
				result_nodes[number].append(node)
			except:
				result_nodes[number] = []
				result_nodes[number].append(node)
		
		return [graph.subgraph(nodes) for nodes in result_nodes.values()]
	
	def clean(self,doors=[]):
		from random import *
		
		#divide
		divisions=[self.g]
		
		breaking_doors=[]
		while len(divisions)< len(self.robots):
			print "divisions",divisions
			import copy
			new_divisions= copy.copy(divisions)
			if (doors):
				door = doors.pop(0)
				for division in new_divisions:
					if door in division.nodes():
						selected_division=division
						new_divisions.remove(division)
						#~ new_divisions+=self.splitGraph(division,door)
						break
			else:
				selected_division = choice(new_divisions)
				new_divisions.remove(selected_division)
				selected_division_doors=[node for node in selected_division if isinstance(node,Door)]
			
				if selected_division_doors:
					door = choice(selected_division_doors)
					#~ new_divisions+=self.splitGraph(selected_division,door)
			
			print door
			new_divisions+=self.splitGraph(selected_division,door)
			
			if len(new_divisions)<=len(self.robots):
				divisions=new_divisions
			breaking_doors.append(door)
				
		print "divisions",divisions
		print "breaking_doors",breaking_doors
		#clean
		for i in range(len(self.robots)):
			rooms =[node for node in divisions[i].nodes() if isinstance(node,Room)]
			for room in rooms:
				clean(self.robots[i],room,self.building)
		
		return divisions
	def benchmarkGraph(self,graph):
		value = 0
		for node in graph.keys():
			if isinstance(node,Room):
				room = node
				value += room.winner.score
		
		return value
	

def walk(robot,to,building,endInDoor=False):
	
	nodes=building.path.shortestPath(robot.node0,to)
	if (endInDoor) and isinstance(to,Room):
		nodes.pop(-1)
	poss=[]
	for i in range(len(nodes)-1):
		if poss:
			pos=poss[len(poss)-1]
		else:
			pos=robot.last_target
		if isinstance(nodes[i],Room):
			room=nodes[i]
			door=nodes[i+1]
			#correcção do bug na posição inicial
			#~ if room is robot.node0:
				#~ pos=robot.pos
			#~ else:
				#~ pos=room.pos
			poss+=room.area.findPath(pos,door.pos)
		elif isinstance(nodes[i+1],Room):
			door=nodes[i]
			room=nodes[i+1]
			#~ poss+=room.area.findPath(door.pos,room.pos)
			poss+=room.area.findPath(pos,room.pos)
		else:
			door1=nodes[i]
			door2=nodes[i+1]
			room=building.path.findConnectiongRoom(door1,door2)
			if room!=None:
				#~ poss+=room.area.findPath(door1.pos,door2.pos)
				poss+=room.area.findPath(pos,door2.pos)
	
	name='Deslocação de '+str(robot.node0)+' para '+str(to)+'.'
	robot.addOrder(name,poss)
	robot.node0=to
	
def clean(robot,room,building):
	walk(robot,room,building,endInDoor=True)
	
	if isinstance(robot.node0,Room):
		poss=[]
		
		pos = robot.last_target
		ordPos=room.winnerPath()#searchAC.bestPath()
		
		pathToArea=room.area.findPath(pos,ordPos[0])#targets[len(robot.targets)-1][1],ordPos[0])
			
		poss+=pathToArea
		poss+=ordPos
			
		name='Limpeza do compartimento '+str(room)+' Com genoma='+str(room.winner.chromosome)#searchAC.winner.chromosome) 
		robot.addOrder(name,poss)


if __name__=='__main__':
	from taskManager import *
	g=GlobalCleanTask(c.robot,c.building)
	g.splitGraph(g.g,c.rooms[12])

